package ide.ccf.ccproject;

import ide.ccf.ccproject.translate.Message;
import ide.ccf.ccproject.wizards.ProjectCreatorListener;

import java.io.File;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.CopyFilesAndFoldersOperation;
import org.eclipse.ui.actions.WorkspaceModifyOperation;

/**
 * CCF项目创建器
 *
 */
public class ProjectCreator 
{
	private IProject project;
	private IPath projectLocation = null;
	private ProjectCreatorListener listener = null;
	private boolean copyToWorkspace = false;
	private Shell shell;

	/**
	 * 构造器
	 * @param project
	 * @param projectLocation
	 */
	public ProjectCreator(IProject project, IPath projectLocation) 
	{
		this(null, project, projectLocation, false);
	}
	
	/**
	 * 构造器
	 * @param shell
	 * @param project
	 * @param projectLocation
	 * @param copyToWorkspace
	 */
	public ProjectCreator(Shell shell, IProject project, IPath projectLocation, boolean copyToWorkspace) 
	{
		this.project = project;
		this.projectLocation = projectLocation;
		this.copyToWorkspace = copyToWorkspace;
		this.shell = shell;
	}

	/**
	 * 添加项目创建器侦听器
	 * @param listener
	 */
	public void addProjectCreatorListener(ProjectCreatorListener listener) 
	{
		this.listener = listener;
	}

	/**
	 * 创建CCF项目
	 * @param runnableContext
	 */
	public void create(IRunnableContext runnableContext) 
	{
		IPath defaultPath = Platform.getLocation();
		
		// 如果项目路径是工作空间路径或者是工作空间直属子节点，那么直接设置项目路径为空，否则IProject.create(...)将会失败并返回异常
		if (defaultPath.equals(projectLocation) || defaultPath.equals(projectLocation.removeLastSegments(1)))
			projectLocation = null;

		final IWorkspace workspace = ResourcesPlugin.getWorkspace();
		final IProjectDescription description = workspace.newProjectDescription(project.getName());
		final IProject newProject = project;
		
		if (!copyToWorkspace)
			description.setLocation(projectLocation);
		else
			description.setLocation(null); // 默认路径

		WorkspaceModifyOperation op = new WorkspaceModifyOperation() 
		{
			protected void execute(IProgressMonitor monitor) throws CoreException 
			{
				try 
				{
					monitor.subTask(Message.ProjectCreator_0);
					newProject.create(description, monitor);
					
					if (monitor.isCanceled())
						throw new OperationCanceledException();
					
					newProject.open(monitor);
					
					if (copyToWorkspace) 
					{
						if (monitor.isCanceled())
							throw new OperationCanceledException();
						
						monitor.subTask(Message.ProjectCreator_1);
						
						CopyFilesAndFoldersOperation copyProc = new CopyFilesAndFoldersOperation(shell);
						String sourcePath = projectLocation.addTrailingSeparator().toOSString();
						File sourceDir = new File(sourcePath);
						String[] copyFileNames = sourceDir.list();
						
						if (copyFileNames != null) 
						{
							for (int i = 0; i < copyFileNames.length; ++i)
								copyFileNames[i] = sourcePath + copyFileNames[i];
							
							copyProc.copyFilesInCurrentThread(copyFileNames, newProject, monitor);
						}
					}
					monitor.subTask(Message.ProjectCreator_2);
					
					if (monitor.isCanceled())
						throw new OperationCanceledException();
					
					if (listener != null)
						listener.projectCreated(newProject, monitor);
					
					newProject.refreshLocal(1, monitor);
					(new CCFProject(newProject)).convertToCCFProject(monitor);
					monitor.done();
				} 
				catch (CoreException ex) 
				{
					IStatus status = ex.getStatus();
					String message = "";

					// 在这种情况下这种异常通常是多状态的，我们需要查找或收集所有不同的错误信息，因为这些多状态信息不会自动做这些工作
					if (!status.isMultiStatus()) 
					{
						message = status.getMessage();
					} 
					else 
					{
						IStatus[] children = status.getChildren();
						for (int i = 0; i < children.length; i++) 
						{
							if (children[i].isOK())
								continue;
							
							message += children[i].getMessage();
						}
					}
					message.trim();
					Shell shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
					MessageDialog.openError(shell, Message.ProjectCreator_3, message);
					monitor.done();
					return;
				}
			}
		};
		try 
		{
			runnableContext.run(false, true, op);
		} 
		catch (InterruptedException e) 
		{
			e.printStackTrace();
		} 
		catch (InvocationTargetException e) 
		{
			e.printStackTrace();
		}
	}

}
